package com.ansion.basedb.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.HandlerThread;
import android.os.Message;
import android.text.TextUtils;

import com.ansion.basedb.dao.helper.AppDatabaseHelper;
import com.ansion.basedb.dao.model.BaseModel;
import com.ansion.basedb.dao.model.DatabaseField;
import com.ansion.basedb.database.sql.SQLTable;
import com.ansion.basetool.preconditions.Preconditions;
import com.ansion.log.S;
import com.ansion.log.VLog;
import com.ansion.utils.BooleanCallback;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;


public class DatabaseManager implements IDatabaseManager {
    private static DatabaseManager databaseManager;
    private AppDatabaseHelper appAppDatabase;
    private DataBaseHandler handler;
    private HashMap<Class<?>, String> uniqueMap;
    private volatile boolean isInited = false;
    private static final String TAG = "DatabaseManager";

    public DatabaseManager() {
        uniqueMap = new HashMap<Class<?>, String>();
    }

    @Override
    public synchronized boolean isInited() {
        return isInited;
    }

    @Override
    public synchronized void setInited(boolean isInited) {
        this.isInited = isInited;
    }

    @Override
    public void preload() {
        appAppDatabase.getReadableDatabase();
    }

    public AppDatabaseHelper getAppDatabase() {
        return appAppDatabase;
    }

    /**
     * 初始化数据化
     *
     * @param context
     * @param dbName
     * @param version
     */
    @Override
    public void initDataBase(Context context, String dbName, int version, List<Class<?>> models, List<SQLTable> tables) {
        if (!isInited()) {
            VLog.d("kop", "dbName = " + dbName);
            if (appAppDatabase == null) {
                appAppDatabase = new AppDatabaseHelper(context, dbName, null,
                        version, models, tables);
            }
            HandlerThread ht = new HandlerThread("dbOption");
            ht.start();
            handler = new DataBaseHandler(appAppDatabase, ht.getLooper());
            setInited(true);
        }
    }

    public synchronized static DatabaseManager getInstance() {
        if (databaseManager == null) {
            databaseManager = new DatabaseManager();
        }
        return databaseManager;
    }

    public static DatabaseManager newInstance() {
        return new DatabaseManager();
    }

    @Override
    public void closeDB() {
        if (appAppDatabase != null) {
            appAppDatabase.close();
            appAppDatabase = null;
        }
    }

    @Override
    public void post(Runnable runnable) {
        if (handler != null) {
            handler.post(runnable);
        }
    }

    @Override
    public <T extends BaseModel> List<T> select(String tableName, Class<T> claz,
                                                String[] columns, String selection, String[] selectionArgs,
                                                String groupBy, String having, String orderBy, String limit) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            VLog.e(TAG, "not init");
            return null;
        }
        if (TextUtils.isEmpty(tableName)) {
            tableName = DatabaseTools.getTableName(claz);
            if (TextUtils.isEmpty(tableName)) {
                VLog.e(TAG, "table name is empty");
                return null;
            }
        }
        SQLiteDatabase database = appAppDatabase.getWritableDatabase();
        if (database != null) {
            Cursor cursor = null;
            List<T> list = null;
            try {
                cursor = database.query(tableName, columns, selection,
                        selectionArgs, groupBy, having, orderBy, limit);

                BaseModel baseModel = claz.newInstance();
                list = baseModel.getModels(cursor);
            } catch (Exception e) {
                VLog.eonly(e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return list;
        }
        return null;
    }

    @Override
    public <T extends BaseModel> List<T> rawQuery(Class<T> claz, String sql, String[] selectionArgs) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            return null;
        }

        SQLiteDatabase database = appAppDatabase.getWritableDatabase();
        if (database != null) {
            Cursor cursor = null;
            List<T> list = null;
            try {
                cursor = database.rawQuery(sql, selectionArgs);
                BaseModel baseModel = claz.newInstance();
                list = baseModel.getModels(cursor);
            } catch (Exception e) {
                VLog.eonly(e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
            return list;
        }
        return null;
    }


    @Override
    public Cursor rawQuery(String sql, String[] selectionArgs) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            return null;
        }
        try {
            SQLiteDatabase database = appAppDatabase.getReadableDatabase();
            if (database != null) {
                Cursor cursor = null;
                try {
                    cursor = database.rawQuery(sql, selectionArgs);
                } catch (Exception e) {
                    VLog.eonly(e);
                    S.e(e);
                }
                return cursor;
            }
        } catch (Throwable t) {
            t.printStackTrace();
            S.e(t);
        }
        return null;
    }


    public void execSql(String sql, Object[] args, BooleanCallback callback) {
        Message msg = Message.obtain();
        msg.what = DatabaseOptionType.OPTION_EXEC_SQL.VALUE;
        msg.obj = new DBSqlObject(sql, args, callback);
        if (null != handler) {
            handler.sendMessage(msg);
        }
    }


    @Override
    public <T extends BaseModel> void insert(String tableName, Class<T> claz, T t,
                                             DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && t != null) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            ContentValues contentValues = null;
            try {
                contentValues = t.getContentValues();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            }
            if (contentValues != null) {
                List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
                DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                condition.model = t;
                condition.contentValues = contentValues;
                contentConditionList.add(condition);
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_INSERT.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void insert(String tableName, Class<T> claz, List<T> models,
                                             DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            List<DBMsgObject.ContentCondition<T>> list = new ArrayList<DBMsgObject.ContentCondition<T>>();
            for (T model : models) {
                ContentValues contentValues = null;
                try {
                    contentValues = model.getContentValues();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                }
                if (contentValues != null) {
                    DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                    condition.contentValues = contentValues;
                    condition.model = model;
                    list.add(condition);
                }
            }
            if (list.size() > 0) {
                msgObj.contentConditionList = list;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_INSERT.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void syncInsert(Class<T> claz, List<T> models) {
        if (appAppDatabase == null) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            String table = DatabaseTools.getTableName(claz);
            SQLiteDatabase database = appAppDatabase
                    .getWritableDatabase();
            if (database == null) {
                return;
            }

            try {
                database.beginTransaction();
                for (T model : models) {
                    ContentValues contentValues = null;
                    try {
                        contentValues = model.getContentValues();
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        VLog.eonly(e);
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        VLog.eonly(e);
                    }
                    if (contentValues == null) {
                        continue;

                    }
                    // retValue=DatabaseUtil.insertNoTx(msg, database);
                    database.insert(table, null, contentValues);
                    // dataChange(table);
                }

                database.setTransactionSuccessful();
            } finally {
                database.endTransaction();
            }
        }
    }



    @Override
    public <T extends BaseModel> long syncInsert(Class<T> claz, T value, boolean bNeedNotify) {
        if (!isInited()) {
            return -1;
        }
        if (appAppDatabase == null) {
            return -1;
        }
        long retValue = -1;
        try {
            if (value != null) {
                Message msg = new Message();
                String table = DatabaseTools.getTableName(claz);
                ContentValues contentValues = null;
                try {
                    contentValues = value.getContentValues();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                }


//				if (false == isWithinTransaction()) {
                SQLiteDatabase database = appAppDatabase
                        .getWritableDatabase();
                if (database == null) {
                    return -1;
                }
                database.beginTransaction();
                try {
//						retValue=DatabaseUtil.insertNoTx(msg, database);
                    database.insert(table, null, contentValues);
                    //dataChange(table);
                    database.setTransactionSuccessful();
                } finally {
                    database.endTransaction();
                }
//					if(bNeedNotify){
//					    dataChange(table);
//					}
//				} else {
//					TLSTransactionObject tlsObj = (TLSTransactionObject) mTls
//							.get();
//					tlsObj.setSyncOpDB(true);
//					tlsObj.getMsgList().add(msg);
//				}
            }
            return retValue;
        } catch (Exception e) {
            VLog.eonly(e);
        } catch (Throwable t) {
            VLog.eonly(t);
        }
        return retValue;
    }

    @Override
    public <T extends BaseModel> void update(String tableName, Class<T> claz, T t,
                                             DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && t != null) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            ContentValues contentValues = null;
            try {
                contentValues = t.getContentValues();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            }
            if (contentValues != null) {
                String unique = getUniqueColumn(claz);
                if (!TextUtils.isEmpty(unique)) {
                    List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
                    DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                    condition.contentValues = contentValues;
                    condition.model = t;
                    condition.whereClause = unique + " = ?";
                    condition.whereArgs = new String[]{contentValues
                            .getAsString(unique)};
                    contentConditionList.add(condition);
                    msgObj.contentConditionList = contentConditionList;
                    msgObj.listener = listener;
                    Message msg = new Message();
                    msg.what = DatabaseOptionType.OPTION_UPDATE.VALUE;
                    msg.obj = msgObj;
                    if (null != handler) {
                        handler.sendMessage(msg);
                    }
                }
            }
        }
    }

    /**
     * @param claz
     * @param t
     * @param needReplaceColumnName 需要更新的字段 {@link DatabaseField}
     * @param listener
     * @param <T>
     */
    @Override
    public <T extends BaseModel> void updateColumn(String tableName, Class<T> claz, T t, List<String> needReplaceColumnName, DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && t != null) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            ContentValues contentValues = null;
            try {
                contentValues = t.getContentValues(needReplaceColumnName);
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            }
            if (contentValues != null) {
                String unique = getUniqueColumn(claz);
                if (!TextUtils.isEmpty(unique)) {
                    List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
                    DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                    condition.contentValues = contentValues;
                    condition.model = t;
                    condition.whereClause = unique + " = ?";
                    condition.whereArgs = new String[]{contentValues
                            .getAsString(unique)};
                    contentConditionList.add(condition);
                    msgObj.contentConditionList = contentConditionList;
                    msgObj.listener = listener;
                    Message msg = new Message();
                    msg.what = DatabaseOptionType.OPTION_UPDATE.VALUE;
                    msg.obj = msgObj;
                    if (null != handler) {
                        handler.sendMessage(msg);
                    }
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void updateColumn(String tableName, Class<T> claz, List<T> list, List<String> needReplaceColumnName, DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && list != null && list.size() > 0) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            String unique = getUniqueColumn(claz);
            if (!TextUtils.isEmpty(unique)) {
                List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<>();
                for (T t : list) {
                    ContentValues contentValues = null;
                    try {
                        contentValues = t.getContentValues(needReplaceColumnName);
                    } catch (IllegalArgumentException | IllegalAccessException e) {
                        VLog.e("TAG_STORAGE", e);
                        continue;
                    }
                    if (contentValues != null) {
                        DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                        condition.contentValues = contentValues;
                        condition.model = t;
                        condition.whereClause = unique + " = ?";
                        condition.whereArgs = new String[]{contentValues.getAsString(unique)};
                        contentConditionList.add(condition);
                    }
                }
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_UPDATE.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void update(String tableName, Class<T> claz, List<T> models,
                                             DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
            String unique = getUniqueColumn(claz);
            if (!TextUtils.isEmpty(unique)) {
                for (T model : models) {
                    ContentValues contentValues = null;
                    try {
                        contentValues = model.getContentValues();
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        VLog.eonly(e);
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        VLog.eonly(e);
                    }
                    if (contentValues != null) {
                        if (!TextUtils.isEmpty(unique)) {
                            String whereClause = unique + " = ?";
                            String whereArgs = contentValues
                                    .getAsString(unique);
                            DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                            condition.whereClause = whereClause;
                            condition.whereArgs = new String[]{whereArgs};
                            condition.contentValues = contentValues;
                            condition.model = model;
                            contentConditionList.add(condition);
                        }
                    }
                }
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_UPDATE.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void replace(String tableName, Class<T> claz, T t, DBOperateAsyncListener listener) {
        if (!isInited()) {
            if (listener != null) {
                listener.onPostExecute(DatabaseOptionType.OPTION_REPLACE, claz, Collections.emptyList(), Collections.emptyList());
            }
            return;
        }
        if (claz != null && t != null) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            ContentValues contentValues = null;
            try {
                contentValues = t.getContentValues();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                VLog.eonly(e);
            }
            if (contentValues != null) {
                List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
                DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                condition.contentValues = contentValues;
                condition.model = t;
                contentConditionList.add(condition);
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_REPLACE.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void replace(String tableName, Class<T> claz, List<T> models,
                                              DBOperateAsyncListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
            for (T model : models) {
                ContentValues contentValues = null;
                try {
                    contentValues = model.getContentValues();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                }
                if (contentValues != null) {
                    DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                    condition.contentValues = contentValues;
                    condition.model = model;
                    contentConditionList.add(condition);
                }
            }
            if (contentConditionList.size() > 0) {
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = listener;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_REPLACE.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void delete(String tableName, Class<T> claz, String whereClause,
                                             String[] whereArgs, DBOperateDeleteListener listener) {
        if (!isInited()) {
            return;
        }
        if (claz != null) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
            DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
            contentConditionList.add(condition);
            if (!TextUtils.isEmpty(whereClause)) {
                condition.whereClause = whereClause;
            }
            if (whereArgs != null && whereArgs.length > 0) {
                condition.whereArgs = whereArgs;
            }
            msgObj.contentConditionList = contentConditionList;
            msgObj.deleteListener = listener;
            Message msg = new Message();
            msg.what = DatabaseOptionType.OPTION_DELETE.VALUE;
            msg.obj = msgObj;
            if (null != handler) {
                handler.sendMessage(msg);
            }
        }
    }

    @Override
    public <T extends BaseModel> void delete(String tableName, Class<T> claz, List<T> models) {
        if (!isInited()) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            DBMsgObject<T> msgObj = new DBMsgObject<T>();
            msgObj.claz = claz;
            msgObj.tableName = tableName;
            List<DBMsgObject.ContentCondition<T>> contentConditionList = new ArrayList<DBMsgObject.ContentCondition<T>>();
            for (T model : models) {
                ContentValues contentValues = null;
                try {
                    contentValues = model.getContentValues();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    VLog.eonly(e);
                }
                if (contentValues != null) {
                    DBMsgObject.ContentCondition<T> condition = new DBMsgObject.ContentCondition<T>();
                    condition.contentValues = contentValues;
                    condition.model = model;
                    contentConditionList.add(condition);
                }
            }
            if (contentConditionList.size() > 0) {
                msgObj.contentConditionList = contentConditionList;
                msgObj.listener = null;
                Message msg = new Message();
                msg.what = DatabaseOptionType.OPTION_DELETE.VALUE;
                msg.obj = msgObj;
                if (null != handler) {
                    handler.sendMessage(msg);
                }
            }
        }
    }

    @Override
    public <T extends BaseModel> void syncReplace(Class<T> claz, List<T> models) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            return;
        }
        if (appAppDatabase == null) {
            return;
        }
        if (claz != null && models != null && models.size() > 0) {
            String table = DatabaseTools.getTableName(claz);
            SQLiteDatabase database = appAppDatabase
                    .getWritableDatabase();
            if (database == null) {
                return;
            }

            database.beginTransaction();
            try {
                for (T model : models) {
                    ContentValues contentValues = null;
                    try {
                        contentValues = model.getContentValues();
                    } catch (IllegalArgumentException e) {
                        VLog.eonly(e);
                    } catch (IllegalAccessException e) {
                        VLog.eonly(e);
                    }
                    if (contentValues == null) {
                        continue;

                    }
                    long row = database.replace(table, null, contentValues);
                }

                database.setTransactionSuccessful();
            } finally {
                database.endTransaction();
            }
        }
    }

    /**
     * @param claz
     * @param whereClause
     * @param whereArgs
     */
    @Override
    public <T extends BaseModel> void syncDelete(Class<T> claz, String whereClause,
                                                 String[] whereArgs) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            return;
        }
        if (appAppDatabase == null) {
            return;
        }
        if (claz != null) {
            String table = DatabaseTools.getTableName(claz);
            SQLiteDatabase database = appAppDatabase
                    .getWritableDatabase();
            if (database == null) {
                return;
            }
            database.beginTransaction();
            try {
                database.delete(table, whereClause, whereArgs);
                database.setTransactionSuccessful();
            } finally {
                database.endTransaction();
            }
        }
    }

    @Override
    public <T extends BaseModel> void syncDelete(String tableName, String whereClause,
                                                 String[] whereArgs) {
        Preconditions.checkNonMainThreadStrictly();
        if (!isInited()) {
            return;
        }
        if (appAppDatabase == null) {
            return;
        }
        String table = tableName;
        SQLiteDatabase database = appAppDatabase
                .getWritableDatabase();
        if (database == null) {
            return;
        }
        database.beginTransaction();
        try {
            database.delete(table, whereClause, whereArgs);
            database.setTransactionSuccessful();
        } finally {
            database.endTransaction();
        }
    }

    @Override
    public <T extends BaseModel> String getUniqueColumn(Class<T> claz) {
        if (!isInited()) {
            return null;
        }
        String unique = uniqueMap.get(claz);
        if (TextUtils.isEmpty(unique)) {
            HashMap<DatabaseField, String> map = DatabaseTools
                    .getDatabaseFields(claz);
            if (map != null && map.size() > 0) {
                Iterator<Entry<DatabaseField, String>> iterator = map
                        .entrySet().iterator();
                String tempUnique = "";
                if (iterator != null) {
                    while (iterator.hasNext()) {
                        Entry<DatabaseField, String> entry = iterator.next();
                        DatabaseField field = entry.getKey();
                        if (field != null) {
                            if (TextUtils.isEmpty(tempUnique)) {
                                tempUnique = field.columnName();
                            }
                            if (field.unique()) {
                                unique = field.columnName();
                                uniqueMap.put(claz, unique);
                                break;
                            }
                        }
                    }
                }
                // 如果没有unique的列,就默认第一列作为unique列
                if (TextUtils.isEmpty(unique) && !TextUtils.isEmpty(tempUnique)) {
                    unique = tempUnique;
                    uniqueMap.put(claz, unique);
                }
            }
        }
        return unique;
    }

    @Override
    public void recycle() {
        closeDB();
        if (handler != null) {
            handler.getLooper().quit();
            handler = null;
        }
        if (uniqueMap != null) {
            uniqueMap.clear();
            uniqueMap = null;
        }
        if (databaseManager != null) {
            databaseManager = null;
        }
    }

    @Override
    public ISqlDataBase getDatabase() {
        return appAppDatabase;
    }

    @Override
    public boolean isEncryptDB() {
        return false;
    }
}
